#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
线性插值实现照片放大四倍（128×128 → 512×512）
"""

from PIL import Image

def linear_interp(v1, v2, t):
    """
    线性插值函数
    v1, v2 : 两端像素值（0~255 整数或 RGB 元组）
    t      : 权重，0 ≤ t ≤ 1
    """
    if isinstance(v1, tuple):          # RGB 三通道
        return tuple(int((1 - t) * a + t * b) for a, b in zip(v1, v2))
    else:                               # 单通道（灰度）
        return int((1 - t) * v1 + t * v2)


def upscale_linear_4x(img):
    """
    将输入图像放大四倍，使用线性插值（等价于双线性插值）。
    参数
    ----
    img : PIL.Image 对象（已转为 RGB 或 L）
    返回
    ----
    out_img : 放大后的 PIL.Image 对象（尺寸 = 4·原尺寸）
    """
    src_w, src_h = img.size
    dst_w, dst_h = src_w * 4, src_h * 4
    out_img = Image.new(img.mode, (dst_w, dst_h))

    src_pixels = img.load()
    dst_pixels = out_img.load()

    # 对每个相邻的 2×2 源像素块进行插值，生成 4×4 目标块
    for y in range(src_h - 1):
        for x in range(src_w - 1):
            # 四个原始像素
            ul = src_pixels[x, y]           # left‑top
            ur = src_pixels[x + 1, y]       # right‑top
            dl = src_pixels[x, y + 1]       # left‑bottom
            dr = src_pixels[x + 1, y + 1]   # right‑bottom

            # 目标块左上角坐标（每个源像素映射到偶数坐标）
            ox, oy = x * 4, y * 4

            # 先把四个角直接拷贝到 4×4 块的四个角
            dst_pixels[ox, oy] = ul
            dst_pixels[ox + 4, oy] = ur
            dst_pixels[ox, oy + 4] = dl
            dst_pixels[ox + 4, oy + 4] = dr

            # 在块内部的每个位置 (i,j)（i,j = 0…4）做双线性插值
            for i in range(5):          # 0‑4 包含四个角
                for j in range(5):
                    # 跳过已经写好的四个角

                    # 水平权重 (左→右) 与垂直权重 (上→下)
                    tx = i / 4.0          # 0‑1
                    ty = j / 4.0

                    # 先在上下两条边做水平插值
                    top    = linear_interp(ul, ur, tx)   # 上边 (ul→ur)
                    bottom = linear_interp(dl, dr, tx)   # 下边 (dl→dr)

                    # 再在左右两条边做垂直插值得到最终像素
                    pixel = linear_interp(top, bottom, ty)

                    dst_pixels[ox + i, oy + j] = pixel

    # ---------- 边界处理 ----------
    # 最右/下两列/行没有右/下相邻像素，直接复制原始像素
    for x in range(src_w):
        for k in range(4):
            dst_pixels[x * 4 + k, dst_h - 4] = src_pixels[x, src_h - 1]
    for y in range(src_h):
        for k in range(4):
            dst_pixels[dst_w - 4, y * 4 + k] = src_pixels[src_w - 1, y]

    # 右下角补齐（复制最后一个像素到 4×4 块的右下角）
    for i in range(4):
        for j in range(4):
            dst_pixels[dst_w - 4 + i, dst_h - 4 + j] = src_pixels[src_w - 1, src_h - 1]

    return out_img


if __name__ == "__main__":
    # ------------------- 参数 -------------------
    input_path  = "lena_128.png"          # 128×128 原图路径
    output_path = "lena_512_linear.png"   # 放大四倍后保存路径
    # -----------------------------------------

    # 读取图像（自动转为 RGB，灰度图可改为 .convert('L')）
    img = Image.open(input_path).convert("RGB")

    # 放大 4 倍
    upscaled = upscale_linear_4x(img)

    # 保存结果
    upscaled.save(output_path)
    print(f"已完成 4 倍放大，保存为 {output_path}")
